#include "gtest/gtest.h"
#include "ReducibleFreeChainComplex.h"

TEST(Cubical, Empty) {
	vector<vector<string> > generators;
	ReducibleFreeChainComplex<string, int> E(2, generators);

	ASSERT_EQ(E.size(0), 0);
	ASSERT_EQ(E.size(1), 0);

	E.reduce();

	ASSERT_EQ(E.size(0), 0);
	ASSERT_EQ(E.size(1), 0);
}

TEST(Cubical, Point) {
	vector<vector<string> > generators(1);
	generators[0].push_back("X");
	ReducibleFreeChainComplex<string, int> E(1, generators);

	ASSERT_EQ(E.size(0), 1);

	E.reduce();

	ASSERT_EQ(E.size(0), 1);
}

TEST(Simplicial, TrianglePerimeter) {
	vector<vector<string> > generators(2);
	generators[0].push_back("A");
	generators[0].push_back("B");
	generators[0].push_back("C");
	generators[1].push_back("a");
	generators[1].push_back("b");
	generators[1].push_back("c");

	ReducibleFreeChainComplex<string, int> E(2, generators);

	E.add_mapping(1, "A", "a", -1);
	E.add_mapping(1, "B", "a", 1);
	E.add_mapping(1, "B", "b", -1);
	E.add_mapping(1, "C", "b", 1);
	E.add_mapping(1, "C", "c", -1);
	E.add_mapping(1, "A", "c", 1);

	ASSERT_EQ(E.size(0), 3);
	ASSERT_EQ(E.size(1), 3);
	ASSERT_EQ(E.size(2), 0);

	E.reduce();
	
	ASSERT_EQ(E.size(0), 1);
	ASSERT_EQ(E.size(1), 1);
	ASSERT_EQ(E.size(2), 0);
}

TEST(Simplicial, Triangle) {
	vector<vector<string> > generators(3);
	generators[0].push_back("A");
	generators[0].push_back("B");
	generators[0].push_back("C");
	generators[1].push_back("a");
	generators[1].push_back("b");
	generators[1].push_back("c");
	generators[2].push_back("Q");

	ReducibleFreeChainComplex<string, int> E(2, generators);

	E.add_mapping(1, "A", "a", -1);
	E.add_mapping(1, "B", "a", 1);
	E.add_mapping(1, "B", "b", -1);
	E.add_mapping(1, "C", "b", 1);
	E.add_mapping(1, "C", "c", -1);
	E.add_mapping(1, "A", "c", 1);
	E.add_mapping(2, "a", "Q", 1);
	E.add_mapping(2, "b", "Q", 1);
	E.add_mapping(2, "c", "Q", 1);

	ASSERT_EQ(E.size(0), 3);
	ASSERT_EQ(E.size(1), 3);
	ASSERT_EQ(E.size(2), 1);

	E.reduce();
	
	ASSERT_EQ(E.size(0), 1);
	ASSERT_EQ(E.size(1), 0);
	ASSERT_EQ(E.size(2), 0);
}

TEST(Cubical, SquarePerimeter) {
	vector<vector<string> > generators(2);
	generators[0].push_back("A");
	generators[0].push_back("B");
	generators[0].push_back("C");
	generators[0].push_back("D");
	generators[1].push_back("a");
	generators[1].push_back("b");
	generators[1].push_back("c");
	generators[1].push_back("d");

	ReducibleFreeChainComplex<string, int> E(1, generators);

	E.add_mapping(1, "A", "a", -1);
	E.add_mapping(1, "B", "a", 1);
	E.add_mapping(1, "B", "b", -1);
	E.add_mapping(1, "C", "b", 1);
	E.add_mapping(1, "D", "c", -1);
	E.add_mapping(1, "C", "c", 1);
	E.add_mapping(1, "A", "d", -1);
	E.add_mapping(1, "D", "d", 1);
	
	ASSERT_EQ(E.size(0), 4);
	ASSERT_EQ(E.size(1), 4);

	E.reduce();
	
	ASSERT_EQ(E.size(0), 1);
	ASSERT_EQ(E.size(1), 1);
}

TEST(Cubical, Square) {
	vector<vector<string> > generators(3);
	generators[0].push_back("A");
	generators[0].push_back("B");
	generators[0].push_back("C");
	generators[0].push_back("D");
	generators[1].push_back("a");
	generators[1].push_back("b");
	generators[1].push_back("c");
	generators[1].push_back("d");
	generators[2].push_back("Q");

	ReducibleFreeChainComplex<string, int> E(2, generators);

	E.add_mapping(1, "A", "a", -1);
	E.add_mapping(1, "B", "a", 1);
	E.add_mapping(1, "B", "b", -1);
	E.add_mapping(1, "C", "b", 1);
	E.add_mapping(1, "D", "c", -1);
	E.add_mapping(1, "C", "c", 1);
	E.add_mapping(1, "A", "d", -1);
	E.add_mapping(1, "D", "d", 1);
	E.add_mapping(2, "a", "Q", 1);
	E.add_mapping(2, "b", "Q", 1);
	E.add_mapping(2, "c", "Q", 1);
	E.add_mapping(2, "d", "Q", 1);

	ASSERT_EQ(E.size(0), 4);
	ASSERT_EQ(E.size(1), 4);
	ASSERT_EQ(E.size(2), 1);

	E.reduce();

	ASSERT_EQ(E.size(0), 1);
	ASSERT_EQ(E.size(1), 0);
	ASSERT_EQ(E.size(2), 0);
}

